package com.example.demo;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.example.demo.service.MyService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@SpringBootApplication(proxyBeanMethods = false, exclude = {
        SecurityAutoConfiguration.class,
        org.flowable.spring.boot.FlowableSecurityAutoConfiguration.class
}
)
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public CommandLineRunner init(final RepositoryService repositoryService,
                                  final MyService myService,
                                  final TaskService taskService) {
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {
                log.info("Number of process definitions : " + repositoryService.createProcessDefinitionQuery().count());
                log.info("Number of tasks : " + taskService.createTaskQuery().count());
                log.info("Number of tasks after process start : " + taskService.createTaskQuery().count());
                myService.createDemoUsers();
            }
        };
    }

    @EnableScheduling
    @RestController
    @RequestMapping("/api")
    public class TestController {

        @GetMapping(value = "/echo")

        public String echo() throws InterruptedException {
            // 配置规则.
            initFlowRules();

            while (true) {
                // 1.5.0 版本开始可以直接利用 try-with-resources 特性，自动 exit entry
                try (Entry entry = SphU.entry("HelloWorld")) {
                    // 被保护的逻辑
                    System.out.println("hello world");
                } catch (BlockException ex) {
                    // 处理被流控的逻辑
                    System.out.println("blocked!");
                    return "OK";
                }
            }
        }


        private void initFlowRules() {
            List<FlowRule> rules = new ArrayList<>();
            FlowRule rule = new FlowRule();
            rule.setResource("HelloWorld");
            rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
            // Set limit QPS to 20.
            rule.setCount(20);
            rules.add(rule);
            FlowRuleManager.loadRules(rules);
        }
    }
}
